/**
 * Copyright (c) 快宝网络 kuaidihelp.com Co., Ltd. All Rights Reserved 禁止外泄以及用于其它的商业用途
 */

import type { ButtonProps } from 'antd';
import { useEffect } from 'react';

interface RecaptchaOpts {
  v3key?: string;
  v2key?: string;
  uniqueId: string;
}

export interface RecaptchaRef {
  timer: NodeJS.Timeout;
  rendered: boolean;
}

export type CaptchaProps = ButtonProps &
  RecaptchaOpts & {
    request: (p: any) => Promise<any>;
    check?: () => Promise<any>;
  };

/**
 *
 * @description 注入script
 * @param key
 */
function insertScript(key?: string) {
  (function (w: any, d, s, q, i) {
    const id = 'grecaptcha';
    if (document.getElementById(id) || !key) {
      return;
    }
    w[q] = w[q] || [];
    const f = d.getElementsByTagName(s)[0];
    const j = d.createElement(s);
    // @ts-ignore
    j.async = true;
    j.id = id;
    // @ts-ignore
    j.src = 'https://www.recaptcha.net/recaptcha/api.js?render=' + i;
    // @ts-ignore
    f.parentNode.insertBefore(j, f);
  })(window, document, 'script', 'grecaptcha', key);
}

/**
 *
 * @description 注入css
 * @param str
 */
function insertCSS(str: string) {
  const style = document.createElement('style');
  const head = document.head || document.getElementsByTagName('head')[0];
  style.type = 'text/css';
  // @ts-ignore
  if (style.styleSheet) {
    // @ts-ignore
    style.styleSheet.cssText = str;
  } else {
    style.appendChild(document.createTextNode(str));
    head.appendChild(style);
  }
}

export interface RecaptchaResult {
  token: string;
  siteKey: string;
}

function execute(v3key?: string): Promise<RecaptchaResult | null> {
  return new Promise((resolve) => {
    const grecaptcha = window.grecaptcha;

    if (!grecaptcha || !v3key) {
      resolve(null);
      return;
    }
    grecaptcha.ready(() => {
      grecaptcha
        .execute(v3key, { action: 'send' })
        .then((token: string) => {
          resolve({ token, siteKey: v3key });
        })
        .catch(() => resolve(null));
    });
  });
}

function render(recaptchaId: string, v2key?: string): Promise<RecaptchaResult | null> {
  return new Promise((resolve) => {
    const grecaptcha = window.grecaptcha;
    if (!grecaptcha || !v2key) {
      resolve(null);
      return;
    }
    grecaptcha.render(recaptchaId, {
      sitekey: v2key,
      callback: (token: string) => {
        resolve({ token, siteKey: v2key });
      },
    });
  });
}

function reset(): Promise<RecaptchaResult | null> {
  return new Promise((resolve) => {
    const grecaptcha = window.grecaptcha;
    if (grecaptcha) {
      grecaptcha.reset();
    }
    resolve(null);
  });
}

export function useRecaptcha(opts: RecaptchaOpts) {
  const { v3key, v2key, uniqueId } = opts;

  useEffect(() => {
    insertScript(v3key);
    insertCSS('.grecaptcha-badge{visibility: hidden;}');
  }, []);

  return [() => execute(v3key), () => render(uniqueId, v2key), () => reset()];
}
